package checkers.inference.model;

import javax.lang.model.element.AnnotationMirror;

import annotations.io.ASTRecord;

/**
 * Represents variables, literals, etc... that have an inherent meaning in the type-system for which we
 * are inferring values.
 *
 * E.g. int literals, or primitive types are always NonNull in the Nullness type system.  Their values
 * will be represented by a ConstantSlot( @NonNull )
 *
 */
public class ConstantSlot extends Slot {

    private final AnnotationMirror value;

    /**
    * @param value   The actual AnnotationMirror that this Constant represents.  This AnnotationMirror should
    *                be valid within the type system for which we are inferring values.
    */
    public ConstantSlot(AnnotationMirror value) {
        this.value = value;
    }

    /**
     * @param astPath Used to locate this constant in code, astPath should point to the tree that has the inherent
     *                constant value
     *                class MyClass {  String s = "a";  }
     *
     *                The ASTPath for the ConstantSlot( NonNull ) generated by "a" would be the path from the root of
     *                the compilation unit to the tree "a"
     *
     *                Note: For now, ConstantSlot ASTPaths are used solely for debugging purposes, as ConstantSlot
     *                annotations never need to be inserted into Jaif Files
     *
     * @param value   The actual AnnotationMirror that this ConstantSlot represents.  This AnnotationMirror should
     *                be valid within the type system for which we are inferring values.
     */
    public ConstantSlot(ASTRecord astPath, AnnotationMirror value) {
        super(astPath);
        this.value = value;
    }

    @Override
    public Object serialize(Serializer serializer) {
        return serializer.serialize(this);
    }

    public AnnotationMirror getValue() {
        return value;
    }

    @Override
    public String toString() {
        return value.toString();
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((value == null) ? 0 : value.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        ConstantSlot other = (ConstantSlot) obj;
        if (value == null) {
            if (other.value != null)
                return false;
        } else if (!value.equals(other.value))
            return false;
        return true;
    }
}
